/************************************************************************
* Programmer:  Philippe Gambling
*
* Course:  CSCI 4534
*
* Date:  April 10, 2009
*
* Environment:  GCC 3.2.2 running on diamond.rocks.uhcl.edu
*
* Files Included: memory_test.c, memory.c, memory.h
*
* Purpose:  To test and demonstrate the functionality of memory object.
*
* Input:  None
*
* Preconditions:  None
*
* Output:  Pass/fail status of each test.
*
* Postconditions: None
*
***********************************************************************/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../memory.h"

#define PASS 1
#define FAIL 0
#define TRUE 1
#define FALSE 0

/*************** Unit Testing Macros ***************************************/
#define START_TEST_DEF(name) int name##_test(void) \
                            { \
                              int result = PASS; \
                              numtests++; \
                              printf("Running %s test... ", #name);
#define END_TEST_DEF if(result==PASS) { \
                        printf("PASSED\n"); \
                      } \
                      else { \
                        printf("\nFAILED\n"); \
                      } \
                      return result; \
                      }
#define RUN_TEST(name) numpassed += name##_test()
#define REPORT_FAIL() printf("\nfailed at line %d",__LINE__); result = FAIL
/***************************************************************************/

int numtests; // Total number of tests run

/******************* UNIT TEST DEFINITIONS *****************************/
START_TEST_DEF(MemorySize)  
  Memory m = new_Memory(15);
  
  if(Memory_Size(m) != 15) { REPORT_FAIL(); }  
  
  free_Memory(m); m = NULL;
END_TEST_DEF

START_TEST_DEF(MemoryPrint)  
  char expectedStr[] = "//////////";
  char actualStr[11] = {0};
  Memory m = new_Memory(10);
  
  if(Memory_Size(m) != 10) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");
  Memory_Print(m,actualStr);  
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }  
  
  printf("\nPrinting Memory\n");
  Memory_Print(m,NULL);  
  
  free_Memory(m); m = NULL;
END_TEST_DEF

START_TEST_DEF(MemoryAllocate)  
  char expectedStr[] = "///////////////";
  char actualStr[16] = {0};
  char id = '0';
  Memory m = new_Memory(15);
  int memSize = 0;
  int index = 0;
  
  if(Memory_Size(m) != 15) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");  
  Memory_Print(m,actualStr);  
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }
    
  memSize = 4; id = 'A';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }    
  
  memSize = 8; id = 'B';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }
  
  memSize = 3; id = 'C';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
  
  memSize = 1; id = 'D';
  if(Memory_Allocate(m,memSize,id) != FALSE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
    
  free_Memory(m); m = NULL;
END_TEST_DEF

START_TEST_DEF(MemoryDeallocate)  
  char expectedStr[] = "////////////////////";
  char actualStr[21] = {0};
  char id = '0';
  Memory m = new_Memory(20);
  int memSize = 0;
  int index = 0;
  
  if(Memory_Size(m) != 20) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");  
  Memory_Print(m,actualStr);  
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }
    
  memSize = 4; id = '0';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }    
  
  memSize = 4; id = 'A';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }
  
  memSize = 10; id = 'B';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
  
  memSize = 4; id = 'C';
  if(Memory_Allocate(m,memSize,id) != FALSE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
    
  memSize = 4; id = 'A'; index = 4;
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  
  memSize = 3; id = 'C';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
  
  memSize = 4; id = 'Z';
  if(Memory_Allocate(m,memSize,id) != FALSE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
  
  memSize = 2; id = 'D';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[18],id,memSize);  
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }          
  
  memSize = 1; id = 'E';
  if(Memory_Allocate(m,memSize,id) != TRUE) { REPORT_FAIL(); }
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  memset(&expectedStr[index],id,memSize);  
  index+=memSize;
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }        
  
  memSize = 4; id = '0'; index = 0;
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  index+=memSize;
  
  memSize = 4; id = 'A';
  if(Memory_Deallocate(m,id) != FALSE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  
  memSize = 3; id = 'C';
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  index+=memSize;  
  
  memSize = 1; id = 'E';
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  index+=memSize;    
  
  memSize = 10; id = 'B';
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  index+=memSize;      
  
  memSize = 2; id = 'D';
  if(Memory_Deallocate(m,id) != TRUE) { REPORT_FAIL(); }  
  printf("\nPrinting Memory\n");    
  memset(&expectedStr[index],'/',memSize);
  Memory_Print(m,actualStr);
  if(strcmp(actualStr,expectedStr) != 0) { REPORT_FAIL(); }            
  
  free_Memory(m); m = NULL;
END_TEST_DEF
/******************* END TEST DEFINITIONS *****************************/

/********************** MAIN THREAD ***********************************/
int main(void) 
{
  int numpassed = 0; // Number of tests passed
  numtests = 0;
  
  printf("Starting Memory tests\n\n");
   
  RUN_TEST(MemorySize);
  RUN_TEST(MemoryPrint);
  RUN_TEST(MemoryAllocate);
  RUN_TEST(MemoryDeallocate);
  
  printf("\n%d of %d tests passed\n",numpassed,numtests);
  if(numpassed != numtests) {
    printf("%d tests FAILED!\n",(numtests-numpassed));
  }
  
  return 0;
}
/****************** END MAIN **************************************/
